#define _GNU_SOURCE
#include "app_bt.h"
#include <string.h>
#include "log/log.h"
#include <fcntl.h>
#include <unistd.h>
#include "app_serial.h"
/**
 * @brief 向蓝牙写入数据前的处理
 * 字符数组处理后变成蓝牙数据格式，1 2 3 XX abc -> 41 54 2b 4d 45 53 48 00 ff ff 61 62 63 0d 0a
        41 54 2b 4d 45 53 48 00： AT+MESH（固定头部）
        ff ff: 对端的MADDR（如果是FFFF代表群发）
        61 62 63: 要发送的数据（不超过12字节）
        0d 0a：\r\n（固定结尾）
 * @param data 待写入的数据，例如：1 2 3 XX abc
 * @param len 数据长度
 * @return int 成功：写入的数据长度，失败：-1
 */
int app_bt_preWrite(char *data, int len)
{
    if (len < 6)
    {
        log_error("数据长度不能小于6");
        return -1;
    }
    int bt_data_len = 8 + 2 + data[2] + 2;
    /*初始化蓝牙数据的缓冲区*/
    char bt_dataBuf[bt_data_len];
    memcpy(bt_dataBuf, "AT+MESH", 8);                /*固定头部，AT+MESH*/
    memcpy(bt_dataBuf + 8, data + 3, 2);             /*id*/
    memcpy(bt_dataBuf + 8 + 2, data + 5, data[2]);   /*数据部分*/
    memcpy(bt_dataBuf + 8 + 2 + data[2], "\r\n", 2); /*固定结尾*/
    /*把缓存数据拷贝到data中*/
    memset(data, 0, len);
    memcpy(data, bt_dataBuf, bt_data_len);
    log_debug("蓝牙数据：%.*s", bt_data_len, data);
    return bt_data_len;
}

static char read_buf[1024]; /*保存蓝牙数据，分几次才能获取完整的数据*/
static int read_buf_len;    /*蓝牙数据的长度*/
static char bt_head[2] = {0xF1, 0xDD};

/**
 * @brief 把有效的数据移动到缓冲区头部
 *
 * @param len
 */
void remove_uselessData(int len)
{
    memmove(read_buf, read_buf + len, read_buf_len - len);
    read_buf_len -= len;
    log_debug("蓝牙数据长度: %d", read_buf_len);
}

/**
 * @brief 读取蓝牙数据后的处理
 *需要注意的点：1.判断是否已经完整接收到了蓝牙数据，if (3 + read_buf[2] > read_buf_len)
 *            2.移动有效数据到缓冲区首部的位置
 *            3.获取到有效蓝牙数据后，移除缓冲区中的蓝牙数据包
 * @param data_buf 保存数据的缓冲区
 * @param len 缓冲区的长度
 * @return int 成功：读取的数据长度，0：还没有得到正确的数据，失败：-1
 */
int app_bt_postRead(char *data_buf, int len)
{
    //log_debug("接收到一份蓝牙数据: %.*s,长度：%d", len, data_buf, len);
    /*把下行缓冲区的数据复制到待处理的数据缓冲区*/
    memcpy(read_buf + read_buf_len, data_buf, len);
    read_buf_len += len;
    /*如果缓冲区数据长度小于8,还需要继续接收蓝牙数据*/
    if (read_buf_len < 8)
    {
        //log_debug("缓冲区数据长度小于8,还需要继续接收蓝牙数据");
        return 0;
    }
    /*开始对接收到的蓝牙数据进行处理*/
    int i;
    for (i = 0; i < read_buf_len - 7; i++)
    {
        if (memcmp(read_buf + i, bt_head, 2) == 0)
        { /*找到了蓝牙数据的固定头部，把数据移动到缓冲区的头部*/
            //log_debug("找到了蓝牙数据的固定头部");
            if (i > 0)
            { /*移除前面无用的数据*/
                remove_uselessData(i);
            }
            /*read_buf[2]表示蓝牙数据的有效长度，数据有效长度大于缓冲区中现有数据长度，说明接收的数据还不完整*/
            if (3 + read_buf[2] > read_buf_len)
            {
                //log_debug("接收的数据还不完整，继续等待接收");
                return 0;
            }
            /*已经接收到完整的蓝牙数据,进行处理；获取到类似：124XXabcd的数据*/
            log_debug("开始处理完整的蓝牙数据");
            memset(data_buf, 0, len);
            data_buf[0] = 1;                                         /*conn_type*/
            data_buf[1] = 2;                                         /*id_len*/
            data_buf[2] = read_buf[2] - 4;                           /*msg_len*/
            memcpy(data_buf + 3, read_buf + 3, 2);                   /*复制id，2字节*/
            memcpy(data_buf + 3 + 2, read_buf + 3 + 4, data_buf[2]); /*复制数据*/

            /*移除缓冲区中的蓝牙数据包*/
            remove_uselessData(3 + data_buf[2]);
            /*返回有效字符数组的长度*/
            return 3 + 2 + data_buf[2];
        }
    }
    /*前面遍历的都不是有用的数据，需要移除*/
    remove_uselessData(i);

    return 0;
}

/*判断蓝牙是否回复ok\r\n*/
static int wait_ack(Device *device)
{
    // usleep(50 * 1000);
    // char buf[4] = {0};
    // read(device->fd, buf, sizeof(buf));

    // if (memcmp(buf, "ok\r\n", 4) == 0)
    // {
    //     return 0;
    // }
    // return -1;

    usleep(50 * 1000);
    // 读取串口数据
    char buf[4];
    read(device->fd, buf, sizeof(buf));
    // 判断是否是OK\r\n
    if (memcmp(buf, "OK\r\n", 4) == 0)
    {
        return 0;
    }
    return -1;
}

/**
 * 测试蓝牙是否可用
 */
int app_bt_status(Device *device)
{
    /*向蓝牙模块写入AT,测试是否回应ok\r\n*/
    write(device->fd, "AT\r\n", 4);

    return wait_ack(device);
}

/**
 * 修改蓝牙名称
 */
int app_bt_rename(Device *device, char *name)
{
    char rename_cmd[50] = {0};
    sprintf(rename_cmd, "AT+NAME%s\r\n", name);
    write(device->fd, rename_cmd, strlen(rename_cmd));

    return wait_ack(device);
}

/**
 * 设置波特率
 */
int app_bt_setBaudRate(Device *device, BTBaudRate baud_rate)
{
    char baud_cmd[50] = {0};
    sprintf(baud_cmd, "AT+BAUD%c\r\n", baud_rate);
    write(device->fd, baud_cmd, strlen(baud_cmd));

    return wait_ack(device);
}

/**
 * 启动蓝牙
 */
int app_bt_reset(Device *device)
{
    write(device->fd, "AT+RESET\r\n", 10);

    return wait_ack(device);
}

/**
 * 设置组网id
 * net_id: 4位16进制字符串
 */
int app_bt_setNetId(Device *device, char *net_id)
{
    char netid_cmd[50] = {0};
    sprintf(netid_cmd, "AT+NETID%s\r\n", net_id);
    write(device->fd, netid_cmd, strlen(netid_cmd));

    return wait_ack(device);
}

/**
 * 设置MAC地址
 * maddr: 4位16进制字符串
 */
int app_bt_setMAddr(Device *device, char *maddr)
{
    char maddr_cmd[50] = {0};
    sprintf(maddr_cmd, "AT+MADDR%s\r\n", maddr);
    write(device->fd, maddr_cmd, strlen(maddr_cmd));

    return wait_ack(device);
}

#define NETID "2222"
static int init_bt(Device *device)
{

    /*初始化串口 9600*/
    app_serial_init(device);

    int rs = app_serial_setBraudRate(device, BR_115200);
    // log_debug("设置串口波特率为115200");
    // 设置串口为非阻塞模式
    app_serial_setBlock(device, 0); 
    tcflush(device->fd, TCIOFLUSH);
    log_debug("设置串口为非阻塞模式，波特率115200");
    if(app_bt_status(device)==0)
    {
        log_debug("bt 115200");
        return 0;
    }
    log_debug("115200  fail");
    return 0;


    if(app_bt_status(device)==0){/*蓝牙可用*/
        log_debug("蓝牙可用，开始修改属性");
        //修改蓝牙属性
        app_bt_rename(device,"TUTU");
        /*修改蓝牙波特率*/
        app_bt_setBaudRate(device,BT_115200);
        

        /*重置蓝牙芯片*/
        app_bt_reset(device);
        sleep(2);
        log_debug("修改蓝牙属性成功");
    }

    /*将串口的波特率改称115200*/
    app_serial_setBraudRate(device,BR_115200);
    tcflush(device->fd,TCSAFLUSH);

    /*组网id*/
    app_bt_setNetId(device,NETID);
    /*mac地址*/
    app_bt_setMAddr(device,"9596");

    if(app_bt_status(device)!=0){
        log_error("蓝牙115200初始化失败");
        return -1;
    }

    /*确认蓝牙可用后，再将串口改为阻塞状态*/
    app_serial_setBlock(device,1);
    tcflush(device->fd,TCSAFLUSH);

    log_debug("蓝牙初始化成功");

    return 0;

}

/**
 * @brief 初始化
 *
 * @param device
 */
int app_bt_Init(Device *device)
{
    device->pre_write = app_bt_preWrite;
    device->post_read = app_bt_postRead;

    return init_bt(device);
}